/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.solr.response;

import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;

import java.util.*;

/**
 * <code>SolrQueryResponse</code> is used by a query handler to return
 * the response to a query request.
 *
 * <p>
 * <a name="returnable_data" /><b>Note On Returnable Data...</b><br/>
 * A <code>SolrQueryResponse</code> may contain the following types of
 * Objects generated by the <code>SolrRequestHandler</code> that processed
 * the request.
 * </p>
 * <ul>
 *  <li>{@link String}</li>
 *  <li>{@link Integer}</li>
 *  <li>{@link Long}</li>
 *  <li>{@link Float}</li>
 *  <li>{@link Double}</li>
 *  <li>{@link Boolean}</li>
 *  <li>{@link Date}</li>
 *  <li>{@link org.apache.solr.search.DocList}</li>
 *  <li>{@link org.apache.solr.common.SolrDocument} (since 1.3)</li>
 *  <li>{@link org.apache.solr.common.SolrDocumentList} (since 1.3)</li>
 *  <li>{@link Map} containing any of the items in this list</li>
 *  <li>{@link NamedList} containing any of the items in this list</li>
 *  <li>{@link Collection} containing any of the items in this list</li>
 *  <li>Array containing any of the items in this list</li>
 *  <li>null</li>
 * </ul>
 * <p>
 * Other data types may be added to the SolrQueryResponse, but there is no guarantee
 * that QueryResponseWriters will be able to deal with unexpected types.
 * </p>
 *
 * @version $Id: SolrQueryResponse.java 898152 2010-01-12 02:19:56Z ryan $
 * @since solr 0.9
 */
public class SolrQueryResponse {

  /**
   * Container for user defined values
   * @see #getValues
   * @see #add
   * @see #setAllValues
   * @see <a href="#returnable_data">Note on Returnable Data</a>
   */
  protected NamedList values = new SimpleOrderedMap();

  /**
   * Container for storing information that should be logged by Solr before returning.
   */
  protected NamedList toLog = new SimpleOrderedMap();

  protected Set<String> defaultReturnFields;

  // error if this is set...
  protected Exception err;

  /**
   * Should this response be tagged with HTTP caching headers?
   */
  protected boolean httpCaching=true;
  
  /***
   // another way of returning an error
  int errCode;
  String errMsg;
  ***/

  public SolrQueryResponse() {
  }
  
  
  /**
   * Gets data to be returned in this response
   * @see <a href="#returnable_data">Note on Returnable Data</a>
   */
  public NamedList getValues() { return values; }

  /**
   * Sets data to be returned in this response
   * @see <a href="#returnable_data">Note on Returnable Data</a>
   */
  public void setAllValues(NamedList nameValuePairs) {
    values=nameValuePairs;
  }

  /**
   * Sets the document field names of fields to return by default when
   * returning DocLists
   */
  public void setReturnFields(Set<String> fields) {
    defaultReturnFields=fields;
  }
  // TODO: should this be represented as a String[] such
  // that order can be maintained if needed?

  /**
   * Gets the document field names of fields to return by default when
   * returning DocLists
   */
  public Set<String> getReturnFields() {
    return defaultReturnFields;
  }


  /**
   * Appends a named value to the list of named values to be returned.
   * @param name  the name of the value - may be null if unnamed
   * @param val   the value to add - also may be null since null is a legal value
   * @see <a href="#returnable_data">Note on Returnable Data</a>
   */
  public void add(String name, Object val) {
    values.add(name,val);
  }

  /**
   * Causes an error to be returned instead of the results.
   */
  public void setException(Exception e) {
    err=e;
  }

  /**
   * Returns an Exception if there was a fatal error in processing the request.
   * Returns null if the request succeeded.
   */
  public Exception getException() {
    return err;
  }

  /**
   * The endtime of the request in milliseconds.
   * Used to calculate query time.
   * @see #setEndTime(long)
   * @see #getEndTime()
   */
  protected long endtime;

  /**
   * Get the time in milliseconds when the response officially finished. 
   */
  public long getEndTime() {
    if (endtime==0) {
      setEndTime();
    }
    return endtime;
  }

  /**
   * Stop the timer for how long this query took.
   * @see #setEndTime(long)
   */
  public long setEndTime() {
    return setEndTime(System.currentTimeMillis());
  }

  /**
   * Set the in milliseconds when the response officially finished. 
   * @see #setEndTime()
   */
  public long setEndTime(long endtime) {
    if (endtime!=0) {
      this.endtime=endtime;
    }
    return this.endtime;
  }
  
  /** Repsonse header to be logged */ 
  public NamedList getResponseHeader() {
	  SimpleOrderedMap<Object> header = (SimpleOrderedMap<Object>) values.get("responseHeader");
	  return header;
  }
  
  /** Add a value to be logged.
   * 
   * @param name name of the thing to log
   * @param val value of the thing to log
   */
  public void addToLog(String name, Object val) {
	  toLog.add(name, val);
  }
  
  /** Get loggable items.
   * 
   * @return things to log
   */
  public NamedList getToLog() {
	  return toLog;
  }
  
  /**
   * Enables or disables the emission of HTTP caching headers for this response.
   * @param httpCaching true=emit caching headers, false otherwise
   */
  public void setHttpCaching(boolean httpCaching) {
    this.httpCaching=httpCaching;
  }
  
  /**
   * Should this response emit HTTP caching headers?
   * @return true=yes emit headers, false otherwise
   */
  public boolean isHttpCaching() {
    return this.httpCaching;
  }
}
